package 压缩流;

import java.io.*;
import java.util.zip.*;

public class UnzipExample {
    public static void main(String[] args) {
        String zipFile = "archive.zip";
        String destDirectory = "extracted";

        // 创建目标目录
        File destDir = new File(destDirectory);
        if (!destDir.exists()) {
            destDir.mkdir();
        }

        try (FileInputStream fis = new FileInputStream(zipFile);
             ZipInputStream zis = new ZipInputStream(fis)) {

            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                String filePath = destDirectory + File.separator + entry.getName();

                // 防止ZIP Slip攻击
                File destFile = new File(filePath);
                String canonicalDestPath = destFile.getCanonicalPath();
                String canonicalDestDir = destDir.getCanonicalPath();

                if (!canonicalDestPath.startsWith(canonicalDestDir + File.separator)) {
                    throw new IOException("恶意ZIP文件: 尝试解压到非法路径 " + entry.getName());
                }

                if (entry.isDirectory()) {
                    // 创建目录
                    if (!destFile.exists()) {
                        destFile.mkdirs();
                    }
                } else {
                    // 确保父目录存在
                    File parent = destFile.getParentFile();
                    if (!parent.exists()) {
                        parent.mkdirs();
                    }

                    // 解压文件
                    try (FileOutputStream fos = new FileOutputStream(destFile);
                         BufferedOutputStream bos = new BufferedOutputStream(fos)) {

                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = zis.read(buffer)) >= 0) {
                            bos.write(buffer, 0, length);
                        }
                    }
                }

                zis.closeEntry();
            }

            System.out.println("ZIP文件解压完成到: " + destDirectory);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}